﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using mshtml;
using SHDocVw;
using AutoPageHelper.Properties;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using System.Threading;
using System.Security.Permissions;
using System.Reflection;
using System.Collections;
using Microsoft.Win32;
using System.Xml;
using System.Diagnostics;
using System.Data.OleDb;
namespace AutoPageHelper
{
    public partial class Form1 : Form
    {
        private PageManager pm = null;
        private bool bFormLoaded = false;
        public Form1()
        {
            InitializeComponent();
            SetDebugLog();
        }
        [Conditional("DEBUG")]
        private void SetDebugLog()
        {
            TextWriterTraceListener log = new TextWriterTraceListener("log.txt");
            Debug.AutoFlush = true;
            Debug.Listeners.Add(log);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
            Screen scr = Screen.FromPoint(this.Location);
            this.Location = new Point(scr.WorkingArea.Right - this.Width - 80, scr.WorkingArea.Top + 80);

            string allSettings = Settings.Default.OperationSettings;
            if (!allSettings.EndsWith(";"))
                allSettings += ";";
            allSettings += Settings.Default.RecordSetting;
            string[] Files = allSettings.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

            mnuSettings.Items.Clear();
            string itemText = "";
            int selectedIndex = 0;
            bool bCmd = (this.Tag != null && !string.IsNullOrEmpty(this.Tag.ToString()));
            if (bCmd)
                Settings.Default.OperationSelected = this.Tag.ToString();
            foreach (string file in Files)
            {
                int index = file.IndexOf(":");
                if (index < 1)
                    continue;
                itemText = file.Substring(0, index);
                index = mnuSettings.Items.Add(itemText);
                if (itemText.Equals(Settings.Default.OperationSelected))
                    selectedIndex = index;
            }
            mnuAutoOpen.Checked = Settings.Default.AutoOpen;
            mnuOptionTop.Checked = Settings.Default.TopMost;
            mnuResumeOnFailed.Checked = Settings.Default.ResumeOnFailed;
            mnuSettings.SelectedIndex = selectedIndex;
            
            if (bCmd)
                btnGetData_Click(sender, e);
            bFormLoaded = true;
        }
        

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (chkAutoFill.Checked)
            {
                if (MessageBox.Show("正在运行，现在要关闭吗？", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
                {
                    e.Cancel = true;
                    return;
                }
                chkAutoFill.Enabled = false;
            }
            Settings.Default.TopMost = mnuOptionTop.Checked;
            Settings.Default.ResumeOnFailed = mnuResumeOnFailed.Checked;
            Settings.Default.AutoOpen = mnuAutoOpen.Checked;
            Settings.Default.OperationSelected = mnuSettings.Text;

            Settings.Default.Save();
            if (pm != null)
            {
                pm.End();
                pm = null;
            }
            Debug.WriteLine("Exit");
        }


        private void mnuOptionSetting_SelectedIndexChanged(object sender, EventArgs e)
        {
            string allSettings = Settings.Default.OperationSettings;
            if (!allSettings.EndsWith(";"))
                allSettings += ";";
            allSettings += Settings.Default.RecordSetting;
            string[] Files = allSettings.Split(new char[] { ';', ':' }, StringSplitOptions.RemoveEmptyEntries);
            int index = 0;
            for (index = 0; index < Files.Length; index+=2)
            {
                if (Files[index].Equals(mnuSettings.Text))
                    break;
            }
            if (index >= Files.Length - 1) // 超出最后一个
                return;
            string file = Path.Combine(Application.StartupPath ,Files[index + 1]);

            try
            {
                mnuGetData.Enabled = false;
                chkAutoFill.Enabled = false;
                bBound = false;
                 if (pm != null)
                    pm.End();
                pm = PageManager.Create(file);
                if (pm== null || pm.Pages.Count < 1)
                    throw new Exception(file);
                pm.OnSubmit += new SubmitHandler(pm_OnSubmit);
                pm.OnFailed += new SubmitHandler(pm_OnFailed);
                pm.OnIEQuit += new SubmitHandler(pm_OnIEQuit);
                Settings.Default.OperationSelected = mnuSettings.Text;
                mnuGetData.Enabled = true;
                if (this.bFormLoaded)
                    btnGetData_Click(sender, e);
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("配置文件加载失败。\r\n" + ex.Message,"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        bool pm_OnIEQuit(object sender, EventArgs e)
        {
            this.Invoke(new EventHandler(Quit));
            return true;
        }
        private void Quit(object sender, EventArgs e)
        {
            //pm.End();
            chkAutoFill.Checked = false;
            chkAutoFill.Enabled = false;
            bBound = false;
            chkAutoFill.FlatAppearance.BorderSize = 0;
            tssProgress.Text = "重取数据";
            tssPrgBar.Visible = false;
        }
        bool pm_OnFailed(object sender, EventArgs e)
        {
            return (bool)this.Invoke(new SubmitHandler(OnFailed), new object[] { sender, e });
        }

        private bool OnFailed(object sender, EventArgs e)
        {
            //bool bContinue = (MessageBox.Show("提交失败，检查配置文件。\r\n继续下一个？", "提示",
            //        MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes);

            bool bContinue = mnuResumeOnFailed.Checked;
            if (bContinue)
            {
                bContinue = MoveNext(false);
                Debug.WriteLine("Next One on failed");
            }
            else
            {
                chkAutoFill.Checked = false;
                string strPa = sender.ToString();
                Debug.WriteLine("Failed:" + strPa);
                MessageBox.Show("在处理当前数据时，因失败停止。----\r\n" + strPa, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return bContinue;
        }

        bool pm_OnSubmit(object sender, EventArgs e)
        {
            return (bool)this.Invoke(new SubmitHandler(MoveNext), new object[] { sender, e });
        }
        
        private bool MoveNext(object sender, EventArgs e)
        {
            return MoveNext();
        }


        private bool MoveNext(bool success = true)
        {
            if (dataGridView1.SelectedRows.Count < 1)
                return false;
            int i, index = dataGridView1.SelectedRows[0].Index; //dataGridView1.CurrentCell.RowIndex;// lstData.SelectedIndex;
            int count = dataGridView1.Rows.Count; //lstData.Items.Count;
            dataGridView1.Rows[index].Selected = false;
            //lstData.SetItemChecked(index, success);
            dataGridView1.Rows[index].Cells[0].Value = (success ? 1 : 0);
            index++;
            Debug.WriteLine("*** line: "+ index + " finished.");

            //if (index >= lstData.Items.Count)
            if (index >= count)
            {
                index = count - 1;
                tssProgress.Text = "完成(" + count + ")";
                i = this.Text.IndexOf('-');
                if (i > 1)
                    this.Text = this.Text.Substring(i + 2);
                chkAutoFill.Checked = false;
                tssPrgBar.Visible = false;
                return false;
            }
            // 选中特定行
            //dataGridView1.CurrentCell = dataGridView1.Rows[index].Cells[1];
            dataGridView1.Rows[index].Selected = true;
            dataGridView1.FirstDisplayedScrollingRowIndex = (index - index % 10);
            //lstData.SelectedIndex = index;
            tssPrgBar.Value = index;
            tssPrgBar.Visible = (tssPrgBar.Value < tssPrgBar.Maximum);
            tssProgress.Text = tssPrgBar.Value + "/" + tssPrgBar.Maximum;
            i = this.Text.IndexOf('%');
            if (i > 0)
                this.Text = this.Text.Substring(i+4);

            this.Text = ((int)((double)tssPrgBar.Value * 100 / tssPrgBar.Maximum + 0.5)) + "%" + " - " + this.Text;
            return true;
        }
        public void MoveFirst()
        {
            dataGridView1.Rows[0].Selected = true;
            dataGridView1.FirstDisplayedScrollingRowIndex = 0;
        }
        private void dataGridView1_DoubleClick(object sender, EventArgs e)
        {
            if (dataGridView1.RowCount < 2)
            {
                btnGetData_Click(sender, e);
            }
        }

        bool bBound = false;
        private void btnGetData_Click(object sender, EventArgs e)
        {
            if (pm == null)
                return;
            for (int i =0; !bBound && i<3; i++)
            {
                bBound = pm.BindWindow();
                if (!bBound && (mnuAutoOpen.Checked && pm.Open()))
                {
                    Thread.Sleep(3000); // 打开后等待页面就绪
                }
                else
                {
                    break;
                }
            }
            this.Activate();
            if (!bBound)
            {
                MessageBox.Show("找不到与【" + Settings.Default.OperationSelected + "】相关的IE窗口，请先用IE打开目标网址后再试一试取数据。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            pm.SavePages = false;
            if (mnuSettings.SelectedIndex == mnuSettings.Items.Count - 1) // last one, record
            {
                tssPrgBar.Visible = false;
                tssProgress.Text = "准备录制";
                chkAutoFill.Enabled = true;
                return;
            }

            try
            {
                int x = GetData(dataGridView1);
                this.Activate();
                if (x > 0)
                {
                    tssPrgBar.Maximum = dataGridView1.Rows.Count; //lstData.Items.Count;
                    tssPrgBar.Value = 0;
                    tssProgress.Text = tssPrgBar.Value + "/" + tssPrgBar.Maximum;
                    chkAutoFill.Enabled = true;
                }
                else if( x == 0)
                {
                    throw new Exception("无法从文件获取指定格式的数据，请参考 选项->帮助。");
                }
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                MessageBox.Show(ex.Message, "错误 - " + this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        private int GetData(DataGridView dgv)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "Excel文件(*.xls;*.xlsx)|*.xls;*.xlsx|数据文件(*.dat)|*.dat|所有文件|*.*";
            dlg.Title = "请为【" + mnuSettings.Text + "】选择数据文件 - " + this.Text;
            DialogResult dr = dlg.ShowDialog();
            int rtnCode = -1;
            if (dr != DialogResult.OK)
                return rtnCode;
            
            string fileName = dlg.FileName;

            try
            {
                string cols = "";
                foreach (string col in pm.Columns)
                {
                    cols += ", [" + col + "]";
                }
                cols = cols.Substring(2);
                ExcelSource es = new ExcelSource(fileName, cols);
                dgv.Columns.Clear();
                if (es.DefaultTable != null)
                {
                    pm.DataSource = es; // 设置数据源
                    DataGridViewCheckBoxColumn chkCol = new DataGridViewCheckBoxColumn();
                    chkCol.FalseValue = "0";
                    chkCol.TrueValue = "1";
                    chkCol.FlatStyle = FlatStyle.Popup;
                    chkCol.Frozen = true;
                    chkCol.HeaderText = ">>";
                    chkCol.Name = "chkCol";
                    chkCol.ReadOnly = true;
                    chkCol.Resizable = DataGridViewTriState.False;
                    chkCol.Width = 24;
                    dgv.Columns.Add(chkCol);
                    dgv.DataSource = es.DefaultTable;
                    // 禁止排序
                    foreach (DataGridViewColumn col in dataGridView1.Columns)
                    {
                        col.SortMode = DataGridViewColumnSortMode.NotSortable;
                    }
                }
                rtnCode = dgv.Rows.Count;
            }
            catch (System.Exception ex)
            {
                rtnCode = -1;
                throw ex;
            }

            //// 日期时间限制
            //Assembly thisAsm = Assembly.GetExecutingAssembly();
            //AssemblyConfigurationAttribute asmConfig = Attribute.GetCustomAttribute(thisAsm, typeof(AssemblyConfigurationAttribute)) as AssemblyConfigurationAttribute;
            //long ticks = Convert.ToInt64(asmConfig.Configuration);
            //DateTime dtExp = new DateTime(ticks);
            //if (DateTime.Now > dtExp)
            //    return -1;

            return rtnCode;
        }

        private bool MovePrevious()
        {
            if (dataGridView1.SelectedRows.Count < 1)
                return false;
            int index = dataGridView1.SelectedRows[0].Index; // dataGridView1.CurrentCell.RowIndex;// lstData.SelectedIndex;
            dataGridView1.Rows[index].Selected = false;
            index--;
            if (index < 0)
            {
                index = 0;
                return false;
            }
            //lstData.SelectedIndex = index;
            //dataGridView1.CurrentCell = dataGridView1.Rows[index].Cells[1];
            dataGridView1.Rows[index].Selected = true;
            dataGridView1.FirstDisplayedScrollingRowIndex = (index - index % 10);

            tssPrgBar.Value = index; 
            tssPrgBar.Visible = (tssPrgBar.Value < tssPrgBar.Maximum);
            tssProgress.Text = tssPrgBar.Value + "/" + tssPrgBar.Maximum;
            
            return true;
        }

        private void chkTop_CheckedChanged(object sender, EventArgs e)
        {
            this.TopMost = mnuOptionTop.Checked;
            this.Opacity =  (mnuOptionTop.Checked) ? 0.85 : 1.0;
        }
        private void chkAutoFill_EnabledChanged(object sender, EventArgs e)
        {
            if (chkAutoFill.Enabled)
            {
                chkAutoFill.ForeColor = Color.Blue;
                chkAutoFill.FlatAppearance.BorderSize = 1;
            }
            else
            {
                chkAutoFill.FlatAppearance.BorderSize = 0;
            }
        }
        private void chkAutoFill_CheckedChanged(object sender, EventArgs e)
        {
            bool bRecord = (mnuSettings.SelectedIndex == mnuSettings.Items.Count - 1); // last one, record
            if (chkAutoFill.Checked) // start
            {
                mnuGetData.Enabled = false;
                chkAutoFill.Text = "停止";
                chkAutoFill.ForeColor = Color.Red;
                mnuSettings.Enabled = false;
                pm.SavePages = bRecord;
                if(bRecord)
                {
                    pm.ReloadPage();
                    tssProgress.Text = "录制中...";
                }
                else // fill
                {
                    ExcelSource es = pm.DataSource as ExcelSource;
                    if (dataGridView1.SelectedRows.Count < 1)
                        MoveFirst();
                    es.RowIndex = dataGridView1.SelectedRows[0].Index;
                    pm.Start();
                }
                
            }
            else // stop
            {
                if (bRecord)
                {
                    pm.SavePages = false;
                    tssProgress.Text = "准备录制";
                }
                else
                {
                    pm.Stop();
                    if (pm.IsRunning)
                        return;
                }
                chkAutoFill.Text = "开始";
                chkAutoFill.ForeColor = Color.Blue;
                mnuGetData.Enabled = true;
                mnuSettings.Enabled = true;
            }
            dataGridView1.Focus(); // checkbox有个小框，去掉
        }


        # region IE右键
        private void AttachContextMenu(string menu)
        {
            string types = Settings.Default.OperationSettings;

            string regkey = @"Software\Microsoft\Internet Explorer\MenuExt\" + menu;
            string scriptPath = Path.Combine(Application.StartupPath, @"StartupAutoPage.htm");
            RegistryKey root = Registry.CurrentUser.OpenSubKey(regkey);
            root = Registry.CurrentUser.CreateSubKey(regkey);
            root.SetValue("", scriptPath, RegistryValueKind.String);
            //root.SetValue("Contexts", 0x000000f3, RegistryValueKind.DWord);
            root.Close();
            // 生成文件
            string titleurl = "";
            string[] SettingFiles = Settings.Default.OperationSettings.Split(new char[] { ';', ':' }, StringSplitOptions.RemoveEmptyEntries);
            int i;
            for (i=0; i<SettingFiles.Length-1; i+=2)
            {
                string xmlfile = Path.Combine(Application.StartupPath, SettingFiles[i+1]);
                try
                {
                    XmlDocument xdoc = new XmlDocument();
                    xdoc.Load(xmlfile);
                    XmlNamespaceManager ns = new XmlNamespaceManager(xdoc.NameTable);
                    ns.AddNamespace("bs", "http://www.sdu.edu.cn/Boson");
                    XmlNode nodeUrl = xdoc.DocumentElement.SelectSingleNode("bs:UrlMain", ns);
                    if (nodeUrl == null)
                        continue;
                    string urlMain = nodeUrl.InnerText;
                    if (string.IsNullOrEmpty(urlMain))
                        continue;
                    titleurl += ",\"" + SettingFiles[i].Trim() + "\",\"" + urlMain.Replace("\\","\\\\").Trim() + "\"";
                }
                catch (System.Exception)
                {
                	// ingore
                }
            }
            if (titleurl.Length > 1)
                titleurl = titleurl.Substring(1);

            string scriptTemplate = Path.Combine(Application.StartupPath, @"Start.htm");
            StreamReader sr = new StreamReader(scriptTemplate);
            StreamWriter sw = new StreamWriter(scriptPath, false, System.Text.Encoding.Unicode);
            i = 2;
            while (!sr.EndOfStream)
            {
                string line = sr.ReadLine();
                if (i > 0)
                {
                    if (line.IndexOf("\"{type,url}\"") > 0)
                    {
                        line = line.Replace("\"{type,url}\"", titleurl);
                        i--;
                    }
                    else if (line.IndexOf("{exepath}") > 0)
                    {
                        line = line.Replace("{exepath}", Application.ExecutablePath.Replace(@"\", @"\\"));
                        i--;
                    }
                }
                
                sw.WriteLine(line);
            }
            sr.Close();
            sw.Close();
            
        }
        private void DeleteContextMenu(string menu)
        {
            string regkey = @"Software\Microsoft\Internet Explorer\MenuExt";
            RegistryKey root = Registry.CurrentUser.OpenSubKey(regkey, true);
            if (root != null)
                root.DeleteSubKey(menu);
        }
        private void mnuContextMenu_Click(object sender, EventArgs e)
        {
            string menuText = "网页数据助手(&D)";
            if (mnuIEContextMenu.Checked)
            {
                // 添加到右键
                AttachContextMenu(menuText);
            }
            else
            {
                // 从右键删除
                DeleteContextMenu(menuText);
            }
        }
        #endregion
        #region 帮助
        private void mnuHelp_Click(object sender, EventArgs e)
        {
            string msg = "请联系开发人员协助解决--13963160076。";
            if (pm == null)
            {
                MessageBox.Show(msg, "帮助与说明", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            string cols = "";
            foreach (string col in pm.Columns)
            {
                cols += col + " ";
            }
            
            if (mnuSettings.SelectedIndex == mnuSettings.Items.Count - 1) // 录制
            {
                msg = "1. 首先关闭所有IE窗口\r\n\r\n2. 用IE8或更高版本IE打开要录制的网址\r\n\r\n3. 点击【取数据】开始录制\r\n\r\n4. 在IE中正常操作、填写数据\r\n\r\n5. 最终结果在Record文件夹中";
            }
            else
            {
                msg = string.Format("1. 用IE8(或以上版本)打开匹配【{0}】的网址：\r\n\t{1}\r\n\r\n2. 点击【取数据】选择数据文件，其中列名必须包含：\r\n\t{2}\r\n\r\n3. 按下【开始】按钮，部分系统需要刷新页面才能继续。",
                mnuSettings.Text, pm.UrlMain, cols);
            }
            
            MessageBox.Show(msg, "帮助与说明", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        #endregion


    }
}